package com.paishen.peiniwan.frame.widget;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.Dialog;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.Scroller;
import android.widget.TextView;

import com.bumptech.glide.Glide;
import com.paishen.common.dialog.BottomMenuDialog;
import com.paishen.common.dialog.BottomMenuDialog.BottomMenu;
import com.paishen.common.util.BaseUtil;
import com.paishen.common.util.LogUtil;
import com.paishen.peiniwan.R;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

public class PictureLayout extends FrameLayout {

    private final View background;

    private int mWidth, mHeight;
    private int originalX, originalY, centerX, centerY;
    private boolean finishAnim;

    private int originalWidth, originalHeight;

    private GestureDetector l;
    private ImageView imgMenu;
    private TextView txCount;
    private DisableTouchViewPager viewPager;
    private int currPosition, initPosition;
    private PictureView currPicture, nextPicture;

    private final List<String> urlList = new ArrayList<>();
    private final List<BottomMenu> menuList = new ArrayList<>();
    private Dialog dlgMenu;

    static final int VIEW_STATE = R.id.frame_picture_adapter_item_state;

    static class ViewState {
        float translateX, translateY, scaleX, scaleY;
    }

    public PictureLayout(Context context) {
        this(context, null);
    }

    public PictureLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        background = new View(context);
        background.setBackgroundColor(0xFF000000);
        addView(background);

        viewPager = new DisableTouchViewPager(context);
        viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {

            private boolean isNextChanged = false;
            private int scrollingPosition;

            @Override
            public void onPageSelected(int position) {
                LogUtil.t("PictureLayout viewPager onPageSelected position:" + position);
                currPosition = position;

                if (urlList.size() > 1) txCount.setText((currPosition + 1) + "/" + urlList.size());
            }

            @Override
            public void onPageScrolled(int position, float percent, int percentPx) {
                LogUtil.t("PictureLayout viewPager onPageScrolled position:" + position + ",percent:" + percent + ",scrollingPosition:"
                        + scrollingPosition);
                if (isNextChanged) {
                    isNextChanged = false;

                    scrollingPosition = position;

                    String currTag = urlList.get(scrollingPosition);
                    if (!TextUtils.isEmpty(currTag)) {
                        currPicture = (PictureView) ((FrameLayout) viewPager.findViewWithTag(currTag)).getChildAt(0);
                    }
                    if (currPicture != null) {
                        ViewState vs = new ViewState();
                        vs.translateX = currPicture.getTranslationX();
                        vs.translateY = currPicture.getTranslationY();
                        vs.scaleX = currPicture.getScaleX();
                        vs.scaleY = currPicture.getScaleY();
                        currPicture.setTag(VIEW_STATE, vs);
                    }

                    if (urlList.size() > scrollingPosition + 1) {
                        String nextTag = urlList.get(scrollingPosition + 1);
                        if (!TextUtils.isEmpty(nextTag)) {
                            nextPicture = (PictureView) ((FrameLayout) viewPager.findViewWithTag(nextTag)).getChildAt(0);
                        }
                        if (nextPicture != null) {
                            ViewState vs = new ViewState();
                            vs.translateX = nextPicture.getTranslationX();
                            vs.translateY = nextPicture.getTranslationY();
                            vs.scaleX = nextPicture.getScaleX();
                            vs.scaleY = nextPicture.getScaleY();
                            nextPicture.setTag(VIEW_STATE, vs);
                        }
                    }
                }

                if (position == scrollingPosition && urlList.size() > scrollingPosition + 1) {
                    if (percent >= 0 && percent <= 1) {
                        if (currPicture != null) {
                            ViewState currVs = (ViewState) currPicture.getTag(VIEW_STATE);
                            if (currVs != null) {
                                if (currVs.scaleX > 1)
                                    currPicture.setScaleX(1 + (currVs.scaleX - 1) * (1 - percent));
                                if (currVs.scaleY > 1)
                                    currPicture.setScaleY(1 + (currVs.scaleY - 1) * (1 - percent));
                                currPicture.setTranslationX(currVs.translateX * (1 - percent));
                                currPicture.setTranslationY(currVs.translateY * (1 - percent));
                            }
                        }

                        if (nextPicture != null) {
                            ViewState nextVs = (ViewState) nextPicture.getTag(VIEW_STATE);
                            if (nextVs.scaleX > 1)
                                nextPicture.setScaleX(1 + (nextVs.scaleX - 1) * percent);
                            if (nextVs.scaleY > 1)
                                nextPicture.setScaleY(1 + (nextVs.scaleY - 1) * percent);
                            nextPicture.setTranslationX(nextVs.translateX * percent);
                            nextPicture.setTranslationY(nextVs.translateY * percent);
                        }
                    }
                }
            }

            @Override
            public void onPageScrollStateChanged(int state) {
                LogUtil.t("PictureLayout viewPager onPageScrollStateChanged state:" + state);
                if (state == ViewPager.SCROLL_STATE_SETTLING) {
                    isNextChanged = true;
                } else if (state == ViewPager.SCROLL_STATE_IDLE) {
                    if (currPosition < urlList.size()) {
                        String currTag = urlList.get(currPosition);
                        if (!TextUtils.isEmpty(currTag)) {
                            FrameLayout pw = (FrameLayout) viewPager.findViewWithTag(currTag);
                            if (pw != null) {
                                currPicture = (PictureView) (pw.getChildAt(0));
                                ViewState vs = new ViewState();
                                vs.translateX = nextPicture.getTranslationX();
                                vs.translateY = nextPicture.getTranslationY();
                                vs.scaleX = nextPicture.getScaleX();
                                vs.scaleY = nextPicture.getScaleY();
                                currPicture.setTag(VIEW_STATE, vs);
                            }
                        }
                    }
                }
            }
        });

        new ViewPagerScroller(getContext()).initViewPagerScroll(viewPager);
        addView(viewPager);

        imgMenu = new ImageView(getContext());
        LayoutParams imgMenuLp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        imgMenuLp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
        final int spacing = BaseUtil.dip2px(10);
        imgMenuLp.setMargins(spacing, spacing, spacing, spacing);
        imgMenu.setPadding(spacing, spacing, spacing, spacing);
        imgMenu.setLayoutParams(imgMenuLp);
        imgMenu.setImageResource(R.mipmap.common_frame_picture_menu);

        imgMenu.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (dlgMenu == null) {
                    LogUtil.e("invoke PictureLayout#initMenuDialog() first !");
                    return;
                }
                if (!dlgMenu.isShowing()) dlgMenu.show();

            }
        });
        addView(imgMenu);
        imgMenu.setVisibility(View.INVISIBLE);

        txCount = new TextView(getContext());
        LayoutParams txCountLp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        txCountLp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
        // final int spacing = BaseUtil.dip2px(10);
        txCountLp.setMargins(0, spacing, 0, 0);
        txCount.setLayoutParams(txCountLp);
        txCount.setTextColor(Color.WHITE);
        addView(txCount);

        l = new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener() {
            private final Runnable runHidden = new Runnable() {
                @Override
                public void run() {
                    hiddenPicture();
                }
            };

            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                if (e.getRawX() > mWidth * 0.2f && e.getRawX() < mWidth * 0.8f
                        && e.getRawY() > mHeight * 0.3f && e.getRawY() < mHeight * 0.7f) {
                    postDelayed(runHidden, 200);
                }
                return false;
            }

            @Override
            public boolean onDoubleTap(MotionEvent e) {
                removeCallbacks(runHidden);
                if (currPicture != null) currPicture.autoSwitchScale();
                return super.onDoubleTap(e);
            }

            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
                return false;
            }

            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                if (velocityX > 1000) {
                    float upX = e1.getRawX();
                    if (upX > mWidth * 0.1f && currPosition > 0) {
                        LogUtil.i("viewPager.setCurrentItem(currPosition - 1);" + (currPosition - 1));
                        viewPager.setCurrentItem(currPosition - 1);
                    }
                } else if (velocityX < -1000) {
                    float upX = e1.getRawX();
                    if (upX < mWidth * 0.9f && currPosition < urlList.size() - 1) {
                        LogUtil.i("viewPager.setCurrentItem(currPosition + 1);" + (currPosition + 1));
                        viewPager.setCurrentItem(currPosition + 1);
                    }
                }
                return false;
            }
        });
    }


    public void initMenuDialog(List<BottomMenu> bList) {
        imgMenu.setVisibility(View.VISIBLE);
        menuList.clear();

//        menuList.add(new ProfileTagEditDialog.Builder.BottomMenu(getContext().getString(R.string.frame_save_photo_to_album), new OnClickListener() {
//            @Override
//            public void onClick(View v) {
//                if (urlList.size() > currPosition) {
//                    PictureView viewPicture = (PictureView) ((FrameLayout) viewPager.findViewWithTag(urlList.get(currPosition))).getChildAt(0);
//
//                    if (viewPicture != null) {
//                        Bitmap image = ((GlideBitmapDrawable) viewPicture.getDrawable()).getBitmap();
//                        String pictureName = C.set.PICTURE_NAME + System.currentTimeMillis() + ".png";
//                        String picturePath = saveImageToSystemAlbum(image, pictureName);
//                        BaseUtil.showToast(R.string.frame_saved_photo_to_album);
//                        EventBus.getDefault().post(new BusEvent(BusEvent.TYPE_MAIN_THREAD, BusEvent.ACTION_PICTURE_SAVE_TO_ALBUM, picturePath));
//                        dlgMenu.dismiss();
//                    }
//                }
//            }
//        }));

        if (bList != null) {
            for (BottomMenu bm : bList) {
                menuList.add(bm);
            }
        }

        dlgMenu = new BottomMenuDialog.Builder(getContext()).setMenuList(menuList).setCancelListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                dlgMenu.dismiss();
            }
        }).create();
    }

    public String getCurrPictureUrl() {
        if (currPosition < urlList.size()) {
            return urlList.get(currPosition);
        }
        return null;
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mWidth = w;
        mHeight = h;
        centerX = w / 2;
        centerY = h / 2;
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        l.onTouchEvent(event);

        if (urlList.size() > currPosition) {
            FrameLayout layWrapper = (FrameLayout) viewPager.findViewWithTag(urlList.get(currPosition));
            if (layWrapper != null) {
                PictureView viewPicture = (PictureView) layWrapper.getChildAt(0);
                if (viewPicture != null) viewPicture.dealTouchEvent(event);
            }
        }
        return super.dispatchTouchEvent(event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return MotionEvent.ACTION_DOWN == event.getAction() ? true : super.onTouchEvent(event);
    }

    public void showPicture(String url, View original) {
        if (TextUtils.isEmpty(url)) throw new IllegalArgumentException("empty img url");

        List<String> mUrlList = new ArrayList<>();
        mUrlList.add(url);
        showPicture(mUrlList, original);
    }

    public void showPicture(List<String> mUrlList, View original) {
        showPicture(mUrlList, 0, original);
    }

    public void showPicture(List<String> mUrlList, int position, final View original) {
        if (mUrlList == null || mUrlList.size() < 1 || position >= mUrlList.size())
            throw new IllegalArgumentException("empty img url or error position");

        String url = mUrlList.get(position);
        if (TextUtils.isEmpty(url)) throw new IllegalArgumentException("empty img url");

        urlList.clear();
        urlList.addAll(mUrlList);
        currPosition = position;
        initPosition = position;

        viewPager.setAdapter(adapter);
        viewPager.setCurrentItem(currPosition);

        if (urlList.size() > 1) txCount.setText((currPosition + 1) + "/" + urlList.size());
        else txCount.setText("");

        int[] location = new int[2];
        original.getLocationOnScreen(location);
        originalWidth = original.getWidth();
        originalHeight = original.getHeight();
        originalX = location[0] + originalWidth / 2;
        originalY = location[1] + originalHeight / 2;


        background.setAlpha(0);
        setVisibility(View.VISIBLE);

        post(new Runnable() {
            @Override
            public void run() {
                if (urlList.size() > currPosition) {
                    String initUrl = urlList.get(currPosition);
                    if (!TextUtils.isEmpty(initUrl)) {
                        FrameLayout shownPicWrapper = (FrameLayout) viewPager.findViewWithTag(initUrl);
                        if (shownPicWrapper != null) {
                            final PictureView viewPicture = (PictureView) shownPicWrapper.getChildAt(0);
                            if (viewPicture != null) {
                                viewPicture.setVisibility(View.VISIBLE);
                                currPicture = viewPicture;
                                ViewState vs = new ViewState();
                                vs.translateX = currPicture.getTranslationX();
                                vs.translateY = currPicture.getTranslationY();
                                vs.scaleX = currPicture.getScaleX();
                                vs.scaleY = currPicture.getScaleY();
                                currPicture.setTag(VIEW_STATE, vs);

                                int iw = currPicture.imageWidth;
                                int ih = currPicture.imageHeight;
                                float originalRelativeScale;
                                if (iw * ih != 0) {
                                    originalRelativeScale = iw <= ih ? originalWidth * vs.scaleX / iw : originalHeight * vs.scaleY / ih;
                                } else {
                                    iw = currPicture.getWidth();
                                    originalRelativeScale = originalWidth * vs.scaleX / iw;
                                }

                                if (originalX != 0 || originalY != 0) {
                                    viewPicture.setTranslationX(originalX - centerX);
                                    viewPicture.setTranslationY(originalY - centerY);
                                }
                                ObjectAnimator anim1 = ObjectAnimator.ofFloat(viewPicture, "translationX", originalX - centerX, 0);
                                ObjectAnimator anim2 = ObjectAnimator.ofFloat(viewPicture, "translationY", originalY - centerY, 0);
                                ObjectAnimator anim3 = ObjectAnimator.ofFloat(viewPicture, "scaleX", originalRelativeScale, vs.scaleX);
                                ObjectAnimator anim4 = ObjectAnimator.ofFloat(viewPicture, "scaleY", originalRelativeScale, vs.scaleY);
                                ObjectAnimator anim6 = ObjectAnimator.ofFloat(background, "alpha", 0, 1);

                                AnimatorSet set = new AnimatorSet();
                                set.play(anim1).with(anim2).with(anim3).with(anim4)
                                        .with(anim6);
                                set.setInterpolator(new DecelerateInterpolator());
                                set.setDuration(400);
                                set.start();
                                set.addListener(new AnimatorListenerAdapter() {


                                    @Override
                                    public void onAnimationEnd(Animator animation) {
                                        super.onAnimationEnd(animation);
                                    }
                                });
                            }
                        }
                    }
                }
            }
        });
    }


    public void hiddenPicture() {
        if (dlgMenu != null && dlgMenu.isShowing()) dlgMenu.dismiss();

        if (urlList.size() > currPosition) {
            if (finishAnim) return;
            finishAnim = true;

            final PictureView viewPicture = (PictureView) ((FrameLayout) viewPager.findViewWithTag(urlList.get(currPosition))).getChildAt(0);
            if (viewPicture == null) return;

            if (initPosition == currPosition) {
                float originalRelativeScale;
                int iw = currPicture.imageWidth;
                int ih = currPicture.imageHeight;
                ViewState vs = (ViewState) viewPicture.getTag(VIEW_STATE);
                if (vs != null) {
                    if (iw * ih != 0) {
                        originalRelativeScale = iw <= ih ? originalWidth * vs.scaleX / iw : originalHeight * vs.scaleY / ih;
                    } else {
                        iw = currPicture.getWidth();
                        originalRelativeScale = originalWidth * vs.scaleX / iw;
                    }
                } else {
                    originalRelativeScale = 1;
                }

                ObjectAnimator anim1 = ObjectAnimator.ofFloat(viewPicture, "translationX", 0, originalX - centerX);
                ObjectAnimator anim2 = ObjectAnimator.ofFloat(viewPicture, "translationY", 0, originalY - centerY);
                ObjectAnimator anim3 = ObjectAnimator.ofFloat(viewPicture, "scaleX", viewPicture.getScaleX(), originalRelativeScale);
                ObjectAnimator anim4 = ObjectAnimator.ofFloat(viewPicture, "scaleY", viewPicture.getScaleY(), originalRelativeScale);
                ObjectAnimator anim6 = ObjectAnimator.ofFloat(background, "alpha", 1, 0);

                AnimatorSet set = new AnimatorSet();
                set.play(anim1).with(anim2).with(anim3).with(anim4).with(anim6);
                set.setDuration(400);
                set.start();
                set.addListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        super.onAnimationEnd(animation);
                        setVisibility(View.GONE);
                        background.setAlpha(1);
                        finishAnim = false;
                    }
                });
            } else {
                ObjectAnimator anim3 = ObjectAnimator.ofFloat(viewPicture, "scaleX", viewPicture.getScaleX(), 2f);
                ObjectAnimator anim4 = ObjectAnimator.ofFloat(viewPicture, "scaleY", viewPicture.getScaleY(), 2f);
                ObjectAnimator anim5 = ObjectAnimator.ofFloat(viewPicture, "alpha", 1, 0);
                ObjectAnimator anim6 = ObjectAnimator.ofFloat(background, "alpha", 1, 0);

                AnimatorSet set = new AnimatorSet();
                set.play(anim3).with(anim4).with(anim6).with(anim5);
                set.setDuration(400);
                set.start();
                set.addListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        super.onAnimationEnd(animation);
                        setVisibility(View.GONE);
                        viewPicture.setAlpha(1f);
                        background.setAlpha(1);
                        finishAnim = false;
                    }
                });
            }

            urlList.clear();
            adapter.notifyDataSetChanged();
        }

    }

    private PagerAdapter adapter = new PagerAdapter() {
        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            FrameLayout viewPictureWrapper = new FrameLayout(getContext());
            PictureView viewPicture = new PictureView(getContext());

            if (currPosition == position) {
                viewPicture.setVisibility(View.INVISIBLE);
            }

            final String url = urlList.get(position);
            viewPictureWrapper.setTag(url); // Glide will setTag use url
            viewPicture.setScaleType(ImageView.ScaleType.CENTER);

            Glide.with(container.getContext()).load(url).asBitmap().fitCenter().into(viewPicture);


            viewPictureWrapper.addView(viewPicture);
            container.addView(viewPictureWrapper);
            return viewPictureWrapper;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            if (urlList.size() > position) {

                FrameLayout viewPictureWrapper = (FrameLayout) container.findViewWithTag(urlList.get(position));
                if (viewPictureWrapper != null) container.removeView(viewPictureWrapper);
            }
        }

        @Override
        public boolean isViewFromObject(View arg0, Object arg1) {
            return arg0 == arg1;
        }

        @Override
        public int getCount() {
            return urlList.size();
        }
    };

    public static class PictureView extends ImageView {
        private int imageWidth, imageHeight;
        private int mWidth, mHeight;
        private int scaleRatioReferWidth;
        private static final float MIN_MIN = 0.5f;
        private static final float MIN_NORMAL = 1f;
        private static final float MAX_MAX = 6f;
        private static final float MAX_NORMAL = 4f;
        private float downX, downY;
        private double downDist;
        private float oldScaleX, oldScaleY;
        private float oldTranslationX, oldTranslationY;
        private float fingersCenterX, fingersCenterY;
        private boolean scaleMode;
        private boolean anim;

        public PictureView(Context context) {
            this(context, null);
        }

        public PictureView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }

        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            LogUtil.t("PictureView onSizeChanged width:" + w + ",height:" + h);

            mWidth = w;
            mHeight = h;

            scaleRatioReferWidth = w / 5;
        }

        @Override
        public void setImageBitmap(Bitmap bm) {
            super.setImageBitmap(bm);
            LogUtil.i("PictureView setImageBitmap width:" + bm.getWidth() + ",height:" + bm.getHeight());
            imageWidth = bm.getWidth();
            imageHeight = bm.getHeight();
        }

        public void dealTouchEvent(MotionEvent event) {
            if (!anim) {
                switch (event.getAction() & MotionEvent.ACTION_MASK) {
                    case MotionEvent.ACTION_DOWN:

                        downX = event.getRawX();
                        downY = event.getRawY();
                        oldTranslationX = getTranslationX();
                        oldTranslationY = getTranslationY();
                        oldScaleX = getScaleX();
                        oldScaleY = getScaleY();
                        break;
                    case MotionEvent.ACTION_POINTER_DOWN:

                        downDist = calcDistanceBetweenFingers(event);
                        downX = event.getRawX();
                        downY = event.getRawY();
                        oldTranslationX = getTranslationX();
                        oldTranslationY = getTranslationY();
                        oldScaleX = getScaleX();
                        oldScaleY = getScaleY();
                        float[] downResult = calcCenterPointBetweenFingers(event);
                        fingersCenterX = downResult[0];
                        fingersCenterY = downResult[1];
                        break;
                    case MotionEvent.ACTION_MOVE:
                        if (downX == 0 && downY == 0) {
                            downX = event.getRawX();
                            downY = event.getRawY();
                            oldTranslationX = getTranslationX();
                            oldTranslationY = getTranslationY();
                            oldScaleX = getScaleX();
                            oldScaleY = getScaleY();
                        }

                        if (event.getPointerCount() > 1) {
                            scaleMode = true;
                            double moveDist = calcDistanceBetweenFingers(event);
                            if (moveDist != downDist) {
                                float changedScaleSize = (float) ((moveDist - downDist) / scaleRatioReferWidth);
                                scalePicture(changedScaleSize);
                            }
                            float[] moveResult = calcCenterPointBetweenFingers(event);
                            if (fingersCenterX != moveResult[0] && fingersCenterY != moveResult[1]) {
                                final float moveX = moveResult[0] - fingersCenterX;
                                final float moveY = moveResult[1] - fingersCenterY;
                                translatePicture(moveX, moveY);
                            }
                        } else if (event.getPointerCount() == 1 && !scaleMode) {
                            final float moveX = event.getRawX() - downX;
                            final float moveY = event.getRawY() - downY;
                            translatePicture(moveX, moveY);
                        }
                        break;
                    case MotionEvent.ACTION_CANCEL:
                    case MotionEvent.ACTION_UP:
                        recoverPictureByAnim();
                        break;
                }
            }
        }

        private void translatePicture(float x, float y) {
            float offset = 0.5f;
            setTranslationX(oldTranslationX + x * oldScaleX * offset);
            setTranslationY(oldTranslationY + y * oldScaleY * offset);
        }

        private void scalePicture(float changedScaleSize) {
            if (oldScaleX + changedScaleSize > MIN_MIN && oldScaleX + changedScaleSize < MAX_MAX) {
                setScaleX(oldScaleX + changedScaleSize);
            }
            if (oldScaleY + changedScaleSize > MIN_MIN && oldScaleY + changedScaleSize < MAX_MAX) {
                setScaleY(oldScaleY + changedScaleSize);
            }
        }

        private boolean scaleState = true;
        private ValueAnimator animAutoScale;

        public void autoSwitchScale() {
            if (animAutoScale != null) {
                animAutoScale.cancel();
                animAutoScale = null;
            }

            animAutoScale = ValueAnimator.ofFloat(0f, 1f);
            scaleState = !scaleState;

            animAutoScale.setInterpolator(new DecelerateInterpolator(2f));
            animAutoScale.setDuration(400);
            animAutoScale.start();
            final float osx = getScaleX();
            final float osy = getScaleY();
            animAutoScale.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    float value = (float) animation.getAnimatedValue();

                    float tmpScaleX = osx - (osx - (scaleState ? 1 : 1.5f)) * value;
                    setScaleX(tmpScaleX);
                    float tmpScaleY = osy - (osy - (scaleState ? 1 : 1.5f)) * value;
                    setScaleY(tmpScaleY);
                }
            });

        }

        private void recoverPictureParameters() {
            downX = 0;
            downY = 0;
            downDist = 0;
            scaleMode = false;
            fingersCenterX = 0;
            fingersCenterY = 0;
        }

        private void recoverPictureByAnim() {

            recoverPictureParameters();

            final float scaleX = getScaleX();
            final float scaleY = getScaleY();
            final float translationX = getTranslationX();
            final float translationY = getTranslationY();

            final float transOffsetX = (imageWidth * scaleX - mWidth) / 2;
            ObjectAnimator anim1 = null;
            if (transOffsetX < 0) {
                anim1 = ObjectAnimator.ofFloat(this, "translationX", translationX, 0);
            } else if (translationX > transOffsetX) {
                anim1 = ObjectAnimator.ofFloat(this, "translationX", translationX, transOffsetX);
            } else if (translationX < -transOffsetX) {
                anim1 = ObjectAnimator.ofFloat(this, "translationX", translationX, -transOffsetX);
            }
            final float transOffsetY = (imageHeight * scaleY - mHeight) / 2;
            ObjectAnimator anim2 = null;
            if (transOffsetY < 0) {
                anim2 = ObjectAnimator.ofFloat(this, "translationY", translationY, 0);
            } else if (translationY > transOffsetY) {
                anim2 = ObjectAnimator.ofFloat(this, "translationY", translationY, transOffsetY);
            } else if (translationY < -transOffsetY) {
                anim2 = ObjectAnimator.ofFloat(this, "translationY", translationY, -transOffsetY);
            }
            ObjectAnimator anim3 = null;
            if (scaleX < MIN_NORMAL) {
                anim3 = ObjectAnimator.ofFloat(this, "scaleX", scaleX, MIN_NORMAL);
            } else if (scaleX > MAX_NORMAL) {
                anim3 = ObjectAnimator.ofFloat(this, "scaleX", scaleX, MAX_NORMAL);
            }
            ObjectAnimator anim4 = null;
            if (scaleY < MIN_NORMAL) {
                anim4 = ObjectAnimator.ofFloat(this, "scaleY", scaleY, MIN_NORMAL);
            } else if (scaleY > MAX_NORMAL) {
                anim4 = ObjectAnimator.ofFloat(this, "scaleY", scaleY, MAX_NORMAL);
            }

            AnimatorSet set = new AnimatorSet();
            AnimatorSet.Builder b = set.play(ObjectAnimator.ofInt(0));
            if (anim1 != null) b.with(anim1);
            if (anim2 != null) b.with(anim2);
            if (anim3 != null) b.with(anim3);
            if (anim4 != null) b.with(anim4);

            set.setInterpolator(new DecelerateInterpolator());
            set.setDuration(400);
            set.start();
            set.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationStart(Animator animation) {
                    super.onAnimationStart(animation);
                    anim = true;
                }

                @Override
                public void onAnimationEnd(Animator animation) {
                    super.onAnimationEnd(animation);
                    anim = false;
                }
            });
        }

        private double calcDistanceBetweenFingers(MotionEvent event) {
            float disX = Math.abs(event.getX(0) - event.getX(1));
            float disY = Math.abs(event.getY(0) - event.getY(1));
            return Math.sqrt(disX * disX + disY * disY);
        }

        private float[] calcCenterPointBetweenFingers(MotionEvent event) {
            float xPoint0 = event.getX(0);
            float yPoint0 = event.getY(0);
            float xPoint1 = event.getX(1);
            float yPoint1 = event.getY(1);
            return new float[]{(xPoint0 + xPoint1) / 2, (yPoint0 + yPoint1) / 2};
        }
    }

    class DisableTouchViewPager extends ViewPager {
        public DisableTouchViewPager(Context context) {
            super(context);
        }

        @Override
        public boolean onInterceptTouchEvent(MotionEvent arg0) {
            return false;
        }

        @Override
        public boolean onTouchEvent(MotionEvent arg0) {
            return false;
        }
    }

    static class ViewPagerScroller extends Scroller {
        private int mScrollDuration = 500;

        public void setScrollDuration(int duration) {
            this.mScrollDuration = duration;
        }

        public ViewPagerScroller(Context context) {
            super(context);
        }

        @Override
        public void startScroll(int startX, int startY, int dx, int dy, int duration) {
            super.startScroll(startX, startY, dx, dy, mScrollDuration);
        }

        @Override
        public void startScroll(int startX, int startY, int dx, int dy) {
            super.startScroll(startX, startY, dx, dy, mScrollDuration);
        }

        public void initViewPagerScroll(ViewPager viewPager) {
            try {
                Field mScroller = ViewPager.class.getDeclaredField("mScroller");
                mScroller.setAccessible(true);
                mScroller.set(viewPager, this);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
